﻿using ICodeShare.UI.Converters.Common;
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;
using ICodeShare.UI.Converters.Extensions;

namespace ICodeShare.UI.Converters
{
    #region IValueConverter
    /// <summary>
    /// 世界时间转换
    /// </summary>
    /// <example>
    /// 1.在xmal文件引用DateConverter类所在命名空间。
    ///   xmlns:cvts="http://schemas.extended.wpf.com/converters"
    /// 2.在xaml文件添加Resources。
    ///   <Window.Resources>
    ///   <cvts:DateTimeToUTCConverter x:Key="cvtsDateTimeToUTC"/>
    ///   </Window.Resources>
    /// 3.在xaml文件中指定Binding值的Converter
    ///   <TextBox Text="{Binding ShowTheText,Converter={StaticResource cvtsDateTimeToUTC}}"></TextBox>
    /// </example>
    [ValueConversion(typeof(DateTime), typeof(DateTime))]
    public sealed class DateTimeToUTCConverter : IValueConverter
    {

        #region  Members 成员变量
        private DateTimeKind _sourceKind;
        private DateTimeKind _targetKind;
        private DateTimeConversionMode _conversionMode;
        private TimeSpan _sourceAdjustment;
        private TimeSpan _targetAdjustment;
        #endregion

        #region  Properties 属性

        #region SourceKind
        /// <summary>
        /// 源时间格式
        /// </summary>
        [ConstructorArgument("sourceKind")]
        public DateTimeKind SourceKind
        {
            get
            {
                return this._sourceKind;
            }

            set
            {
                value.AssertEnumMember("value", DateTimeKind.Local, DateTimeKind.Unspecified, DateTimeKind.Utc);
                this._sourceKind = value;
            }
        }
        #endregion

        #region TargetKind
        /// <summary>
        /// 目标时间格式
        /// </summary>
        /// <remarks>
        [ConstructorArgument("targetKind")]
        public DateTimeKind TargetKind
        {
            get
            {
                return this._targetKind;
            }

            set
            {
                value.AssertEnumMember("value", DateTimeKind.Local, DateTimeKind.Unspecified, DateTimeKind.Utc);
                this._targetKind = value;
            }
        }
        #endregion

        #region SourceAdjustment
        /// <summary>
        /// 源时间调整值TimeSpan.
        /// </summary>
        public TimeSpan SourceAdjustment
        {
            get { return this._sourceAdjustment; }
            set { this._sourceAdjustment = value; }
        }
        #endregion

        #region TargetAdjustment
        /// <summary>
        /// 目标时间调整值TargetAdjustment
        /// </summary>
        public TimeSpan TargetAdjustment
        {
            get { return this._targetAdjustment; }
            set { this._targetAdjustment = value; }
        }
        #endregion

        #region ConversionMode
        /// <summary>
        /// 时间格式间的转换方式
        /// </summary>
        /// <remarks>
        /// 如果调整方式为DateTimeConversionMode.DoConversion，则转换中时间会被调整。
        /// 如果调整方式为DateTimeConversionMode.SpecifyKindOnly，则转换中时间不被调整。
        /// </remarks>
        public DateTimeConversionMode ConversionMode
        {
            get
            {
                return this._conversionMode;
            }

            set
            {
                value.AssertEnumMember("value", DateTimeConversionMode.DoConversion, DateTimeConversionMode.SpecifyKindOnly);
                this._conversionMode = value;
            }
        }
        #endregion

        #endregion

        #region Constructors 构造函数
        /// <summary>
        /// Initializes a new instance of the DateTimeConverter class
        /// </summary>
        public DateTimeToUTCConverter()
        {
        }

        /// <summary>
        /// Initializes a new instance of the DateTimeConverter class with the specified source and target kinds.
        /// </summary>
        /// <param name="sourceKind">
        /// The source kind for converted <see cref="DateTime"/>s.
        /// </param>
        /// <param name="targetKind">
        /// The target kind for converted <see cref="DateTime"/>s.
        /// </param>
        public DateTimeToUTCConverter(DateTimeKind sourceKind, DateTimeKind targetKind)
        {
            this.SourceKind = sourceKind;
            this.TargetKind = targetKind;
        }
        #endregion

        #region  Base Class Overrides 基类方法重写
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is DateTime)
            {
                return DoConversion(this.ConversionMode, (DateTime)value, this.TargetKind, this.TargetAdjustment);
            }

            return DependencyProperty.UnsetValue;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is DateTime)
            {
                return DoConversion(this.ConversionMode, (DateTime)value, this.SourceKind, this.SourceAdjustment);
            }

            return DependencyProperty.UnsetValue;
        }
        #endregion

        #region Methods 方法
        /// <summary>
        /// 世界时间转换
        /// </summary>
        /// <param name="conversionMode">时间转换方式</param>
        /// <param name="dateTime">源时间</param>
        /// <param name="convertTo">目标格式</param>
        /// <param name="adjustment">目标时间调整值</param>
        /// <returns></returns>
        private static DateTime DoConversion(DateTimeConversionMode conversionMode, DateTime dateTime, DateTimeKind convertTo, TimeSpan adjustment)
        {
            if (adjustment != TimeSpan.Zero)
            {
                dateTime = dateTime.Add(adjustment);
            }

            if (conversionMode == DateTimeConversionMode.DoConversion)
            {
                switch (convertTo)
                {
                    case DateTimeKind.Local:
                        return dateTime.ToLocalTime();
                    case DateTimeKind.Utc:
                        return dateTime.ToUniversalTime();
                    default:
                        return dateTime;
                }
            }
            else
            {
                return DateTime.SpecifyKind(dateTime, convertTo);
            }
        }
        #endregion
    }
    #endregion

    
}
